﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PacketRush.Core;
using System.Net;

namespace TestServer
{
    public partial class MainForm : Form
    {
        NetServer _NetServer;
        System.Timers.Timer _ServerTimer;
        volatile bool _ServerRunning = false;
        volatile bool _Updating = false;
        public ConnectionListForm ConnectionListForm { get; set; }
        volatile bool _ServerPropertiesFocused = false;
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            ConnectionListForm = new ConnectionListForm();
            ConnectionListForm.Show(this);
        }

        private void StartServer()
        {
            if (_NetServer == null)
            {
                ReliableUdpServerNetworkingProvider netProvider = new ReliableUdpServerNetworkingProvider();
                netProvider.BeforeUpdate +=new EventHandler<ReliableUdpEventArgs>(NetProvider_BeforeUpdateConnection);
                _NetServer = new NetServer(netProvider, IPAddress.Parse("127.0.0.1"), 50000);
                NetServerPropertyGrid.SelectedObject = _NetServer;

                _NetServer.Error += new EventHandler<NetErrorEventArgs>(NetServer_Error);
                _NetServer.Connected += new EventHandler<NetEventArgs>(NetServer_Connected);
                _NetServer.Disconnected += new EventHandler<NetEventArgs>(NetServer_Disconnected);
                _NetServer.Start();
                _ServerTimer = new System.Timers.Timer(1);
                _ServerTimer.Elapsed += new System.Timers.ElapsedEventHandler(ServerTimer_Elapsed);
                _ServerRunning = true;
                _ServerTimer.Start();
                OutputTextBox.Invoke(new Action<string>(AddOutputMessage), "Server started.");

            }
        }

        void NetProvider_BeforeUpdateConnection(object sender, ReliableUdpEventArgs e)
        {
            ConnectionListForm.Invoke(new Action<string, string, string>(ConnectionListForm.UpdateConnectionRow), e.Connection.Id.ToString(), e.Connection.NumPacketsWaitingAcknowledgement.ToString(), e.Connection.Latency.ToString());
        }

        void ServerTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!_Updating)
            {
                _Updating = true;
                if (_ServerRunning)
                {
                    try
                    {
                        _NetServer.Update();

                        NetServerPropertyGrid.Invoke(new Action(() => { if (!NetServerPropertyGrid.ContainsFocus) NetServerPropertyGrid.Refresh(); }));

                    }
                    catch (Exception x)
                    {
                        OutputTextBox.Invoke(new Action<string>(AddOutputMessage), x.Message + "\r\n" + x.StackTrace);

                    }
                }
                else
                {
                    _ServerTimer.Stop();
                    _NetServer.Stop();

                    _ServerTimer = null;
                    _NetServer = null;

                    TopToolBar.Invoke(new Action(() => { StartServerButton.Enabled = true; }));
                    OutputTextBox.Invoke(new Action<string>(AddOutputMessage), "Server stopped.");
                }

                _Updating = false;
            }
        }

        void NetServer_Disconnected(object sender, NetEventArgs e)
        {
            INetConnection connection = _NetServer.GetConnectionById(e.ConnectionId);
            ConnectionListForm.Invoke(new Action<string>(ConnectionListForm.RemoveConnectionRow), connection.Id.ToString());
        }

        void NetServer_Connected(object sender, NetEventArgs e)
        {
            INetConnection connection = _NetServer.GetConnectionById(e.ConnectionId);
            ConnectionListForm.Invoke(new Action<string, string, string, string>(ConnectionListForm.AddConnectionRow), connection.Id.ToString(), connection.RemoteEndPoint.ToString(), "0", connection.Latency.ToString());
        }

        void NetServer_Error(object sender, NetErrorEventArgs e)
        {
            OutputTextBox.Invoke(new Action<string>(AddOutputMessage), e.SocketErrorCode.ToString());
        }

        public void AddOutputMessage(string message)
        {
            OutputTextBox.Text += "\r\n> " + message;
            OutputTextBox.Select(OutputTextBox.Text.Length - 1, 0);
            OutputTextBox.ScrollToCaret();
        }

        private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void StartServerButton_Click(object sender, EventArgs e)
        {
            if (!_ServerRunning)
            {
                StartServer();
            }
            else
            {
                _ServerRunning = false;
                StartServerButton.Enabled = false;
            }
        }

        private void NetServerPropertyGrid_Enter(object sender, EventArgs e)
        {
            _ServerPropertiesFocused = true;
        }

        private void NetServerPropertyGrid_Leave(object sender, EventArgs e)
        {
            _ServerPropertiesFocused = false;
        }

        private void NetServerPropertyGrid_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {

        }
    }
}
